home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / nihcl-30.lha / nihcl-3.0 / ex / BigInt.c < prev    next >
C/C++ Source or Header  |  1990-05-15  |  5KB  |  144 lines

  1. // BigInt.c -- Multiple-precision integer class
  2.  
  3. // $Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/ex/RCS/BigInt.c,v 3.0 90/05/15 22:43:26 kgorlen Rel $
  4.  
  5. #include "BigInt.h"
  6. #include <string.h>
  7. #include <ctype.h>
  8.  
  9. BigInt::BigInt(const char* digitString)
  10. {
  11.     unsigned n = strlen(digitString);
  12.     if (n != 0) {
  13.         digits = new char[ndigits=n];
  14.         char* p = digits;
  15.         const char* q = &digitString[n];
  16.         while (n--) *p++ = *--q - '0';  // convert ASCII digit
  17.                                         // to binary
  18.     }
  19.     else {                              // empty string
  20.         digits = new char[ndigits=1];
  21.         digits[0] = 0;
  22.     }
  23. }
  24.  
  25. BigInt::BigInt(unsigned n)
  26. {
  27.     char d[3*sizeof(unsigned)+1];   // buffer for decimal digits
  28.     char* dp = d;                   // pointer to next
  29.                                     // decimal digit
  30.     ndigits = 0;
  31.     do {                            // convert integer to
  32.                                     // decimal digits
  33.         *dp++ = n%10;
  34.         n /= 10;
  35.         ndigits++;
  36.     } while (n > 0);
  37.     digits = new char[ndigits];     // allocate space for
  38.                                     // decimal digits
  39.     for (register i=0; i<ndigits; i++) digits[i] = d[i];
  40. }
  41.  
  42. BigInt::BigInt(const BigInt& n)
  43. {
  44.     unsigned i = n.ndigits;
  45.     digits = new char[ndigits=i];
  46.     char* p = digits;
  47.     char* q = n.digits;
  48.     while (i--) *p++ = *q++;
  49. }
  50.  
  51. void BigInt::operator=(const BigInt& n)
  52. {
  53.     if (this == &n) return;     // to handle x = x correctly
  54.     delete digits;
  55.     unsigned i = n.ndigits;
  56.     digits = new char[ndigits=i];
  57.     char* p = digits;
  58.     char* q = n.digits;
  59.     while (i--) *p++ = *q++;
  60. }
  61.  
  62. BigInt BigInt::operator+(const BigInt& n) const
  63. {
  64.     unsigned maxDigits =
  65.         (ndigits>n.ndigits ? ndigits : n.ndigits)+1;
  66.     char* sumPtr = new char[maxDigits];
  67.     BigInt sum(sumPtr,maxDigits); // allocate storage for sum
  68.     DigitStream a(*this);
  69.     DigitStream b(n);
  70.     unsigned i = maxDigits;
  71.     unsigned carry = 0;
  72.     while (i--) {
  73.         *sumPtr = (a++) + (b++) + carry;
  74.         if (*sumPtr >= 10) {
  75.             carry = 1;
  76.             *sumPtr -= 10;
  77.         }
  78.         else carry = 0;
  79.         sumPtr++;
  80.     }
  81.     return sum;
  82. }
  83.  
  84. void BigInt::print(FILE* f) const
  85. {
  86.     for (int i = ndigits-1; i >= 0; i--) fprintf(f,"%d",digits[i]);
  87. }
  88.  
  89. void BigInt::scanFrom(istream& strm)
  90. {
  91.     delete digits;
  92.     ndigits = 0;  digits = NULL;
  93.     strm >> ws;                     // skip leading whitespace
  94.     scanChunk(strm);
  95. }
  96.  
  97. char* BigInt::scanChunk(istream& strm)
  98. {
  99.     const unsigned CHUNKSIZE = 3;   // read CHUNKSIZE digits
  100.                                     // at a time
  101.     char chunk[CHUNKSIZE];          // buffer to hold digits read
  102.     register char* p = chunk;       // pointer to digit buffer
  103.     register char* q;               // pointer to BigInt
  104.                                     // object digits
  105.     register i;                     // digits read in this chunk
  106. // read a chunk of digits until eof or non-digit
  107.     for (i=0; i<CHUNKSIZE; i++) {   // read a chunk of digits
  108.         strm.get(*p);               // get next character
  109.         if (!strm.eof() && isdigit(*p)) 
  110.             *p++ -= '0';            // convert to digit
  111.         else {                      // encountered eof or non-digit
  112.             ndigits += i;           // now we know the number
  113.                                     // of digits
  114.             if (ndigits != 0) {     // save digits just read
  115.                 q = digits = new char[ndigits];
  116.                 for (; i>0; i--) *q++ = *--p;
  117.                 return q;           // q now points after
  118.                                     // last digit
  119.             }
  120.             else {                  // failed to find any digits,
  121.                                     // so set istream state to fail
  122.                 strm.clear(strm.rdstate() | ios::failbit);
  123.                 return NULL;
  124.             }
  125.         }
  126.     }
  127. // At his point we have read CHUNKSIZE digits into chunk, and
  128. // there may still be digits left on the input stream, so
  129. // call scanChunk() recursively to read the next chunk.
  130.     ndigits += i;                   // add no. of digits just read
  131.     q = scanChunk(strm);            // q now points after
  132.                                     // last digit
  133.     if ( q==NULL ) return NULL;
  134.     for (; i>0; i--) *q++ = *--p;   // add digits just read
  135.     return q;                       // q now points after
  136.                                     // last digit
  137. }
  138.  
  139. void BigInt::printOn(ostream& strm) const
  140. {
  141.     for (register i = ndigits-1; i >= 0; i--)
  142.         strm << (int)digits[i];
  143. }
  144.